Let's start with some basics in financial markets analysis! We'll use python (https://www.python.org/) as programming language, starting with pandas (http://pandas.pydata.org/), a well-renowned module for data manipulation and analysis. First of all, let's import the modules we need.
In [1]:
import pandas as pd
import pandas_datareader.data as web
import matplotlib.pyplot as plt
# Defines the chart color scheme using Tableu's Tableau10
plt.style.use('https://gist.githubusercontent.com/mbonix/8478091db6a2e6836341c2bb3f55b9fc/raw/7155235ed03e235c38b66c160d402192ad4d94d9/tableau10.mplstyle')
%matplotlib inline
Then, let's choose a bunch of stocks to analyze. They are: Apple (AAPL), Alphabet (former Google, GOOGL), Microsoft (MSFT), McDonald's (MCD), Coca-Cola (KO). Three technology companies and two food & beverage stocks.
In [18]:
# List of stocks tickers
STOCKS = ['NASDAQ:AAPL', 'NASDAQ:GOOGL', 'NASDAQ:MSFT', 'NYSE:MCD', 'NYSE:KO']
# Analysis period
START = '12-30-2006'
END = '12-31-2016'
Now, let's download stock data from Yahoo!Finance, using pandas-datareader module.
In [23]:
data = web.DataReader(STOCKS, 'google', pd.to_datetime(START), pd.to_datetime(END))
We'll work only on Close prices, so let's discard the other data.
In [24]:
prices = data.loc['Close', :, :]
prices.tail(10)
Out[24]:
Now, let's plot prices.
In [25]:
prices.plot(figsize=(10, 8), title='Stock prices');
Alphabet, or Google, seems to be the winner in these 10 years. But comparison of stocks is difficult because of different ranges of prices. Let's try to normalize them, rebasing to 100.
In [26]:
norm_prices = 100 * prices / prices.iloc[0, :]
norm_prices.head(10)
Out[26]:
Now, a plot of rebased prices.
In [32]:
norm_prices.plot(figsize=(10, 8), title='Stock prices ({} = 100)'.format(START));
Now, it's clear that Apple and not Alphabet was the winner. Which was its return over the period, anyway? Let's calculate it!
In [28]:
absolute_returns = (norm_prices.iloc[-1, :]).to_frame().T
absolute_returns.index = ['Absolute Return (%)']
absolute_returns
Out[28]:
An astonishing 967.59%! Or a 26.72% compound annual return, if you prefer.
In [29]:
compound_returns = 100 * ((1 + absolute_returns / 100) ** 0.1 - 1)
compound_returns.index = ['Compound Annual Return (%)']
compound_returns
Out[29]:
Now, let's resample data into yearly percent returns.
In [30]:
yearly_returns = prices.resample('A').last().pct_change()
yearly_returns
Out[30]:
Then, let's plot the returns.
In [49]:
ax = yearly_returns.plot(figsize=(10, 8), title='Stock yearly returns', ls='', marker='o');
ax.set_xlim(ax.get_xlim()[0], ax.get_xlim()[1] + 1)
ax.axhline(0, color='gray');
And let's see how returns averaged in the period.
In [54]:
yearly_avgs = yearly_returns.mean().to_frame().T
yearly_avgs.index = ['Average Yearly Return (%)']
yearly_avgs
Out[54]:
Then we can compute yearly logarithmic returns over the period.
In [55]:
import numpy as np
yearly_log_returns = prices.resample('A').last().apply(np.log).diff()
yearly_log_returns
Out[55]:
Let's also plot log returns.
In [56]:
ax = yearly_log_returns.plot(figsize=(10, 8), title='Stock yearly log returns', ls='', marker='o');
ax.set_xlim(ax.get_xlim()[0], ax.get_xlim()[1] + 1)
ax.axhline(0, color='gray');
Again, let's compute averages. Quite different from percent returns, aren't they?
In [57]:
yearly_log_avgs = yearly_log_returns.mean().to_frame().T
yearly_log_avgs.index = ['Average Yearly Log Return (%)']
yearly_log_avgs
Out[57]:
We always can transform percent returns into log returns:
In [58]:
(1 + yearly_returns).apply(np.log)
Out[58]:
And vice versa:
In [59]:
(yearly_log_returns).apply(np.exp) - 1
Out[59]:
If we plot daily returns, we can clearly see a different scale over time and across stocks. Let's try with Apple and McDonald's.
In [64]:
prices.loc[:, ['NASDAQ:AAPL', 'NYSE:MCD']].pct_change().plot(figsize=(10, 8), title="Apple and McDonald's daily returns")
Out[64]:
That leads us to a new topic: volatility, i.e. variability of returns. But this is a topic which deserves a new anaysis. To be continued...